#include "hal_rcc.h"
#include "zf_common_clock.h"
#include "zf_common_interrupt.h"
#include "zf_driver_gpio.h"

#include "zf_driver_uart.h"
#include "zf_driver_dma.h"
#include "zf_driver_lpuart.h"
#include "hal_lpuart.h"

LPUART_Type*lpuart_index[1]={LPUART};

static IRQn_Type lpuart_irq[1]={LPUART_IRQn};

void lpuart_init(lpuart_index_enum lpuart_n,LPUART_Baudrate_Type baud,lpuart_tx_pin_enum tx_pin,lpuart_rx_pin_enum rx_pin)
{
    afio_init((gpio_pin_enum)((tx_pin&0xFFF00)>>8),GPO,(gpio_af_enum)((tx_pin&0xF0)>>4),GPO_AF_PUSH_PULL);   // 提取对应IO索引 AF功能编码
    afio_init((gpio_pin_enum)((rx_pin&0xFFF00)>>8),GPI,(gpio_af_enum)((rx_pin&0xF0)>>4),GPI_FLOATING_IN);    // 提取对应IO索引 AF功能编码
    
    switch(lpuart_n)
    {
        case LPUART_1:
        {
            RCC_EnableAPB2Periphs(RCC_APB2_PERIPH_LPUART,ZF_ENABLE);
            /* LPUART clock source select at LSE(32.768KHz). */
            RCC->BDCR|=RCC_BDCR_DBP_MASK; /* Allow access to backup registers */
            RCC->BDCR|=RCC_BDCR_BDRST_MASK;
            RCC->BDCR&=~RCC_BDCR_BDRST_MASK;
            RCC->CFGR2|=RCC_CFGR2_LPUARTCLKSEL(0u);  /* Selcect LSE oscillator as LPUART clock */
            RCC->BDCR|=RCC_BDCR_LSEON_MASK;  /* Enable LSE */
            break;
        }
    }
    
    LPUART_Init_Type lpuart_init;
    lpuart_init.ClockSource=LPUART_ClockSource_LSE;
    lpuart_init.BaudRate=baud;
    lpuart_init.WordLength=LPUART_WordLength_8;
    lpuart_init.StopBits=LPUART_StopBits_1;
    lpuart_init.Parity=LPUART_Parity_None;
    
    LPUART_Init(lpuart_index[lpuart_n],&lpuart_init);
    while(!(lpuart_index[lpuart_n]->LPUEN&LPUART_LPUEN_TXEN_MASK))
        lpuart_index[lpuart_n]->LPUEN|=LPUART_LPUEN_TXEN_MASK;
    while(!(lpuart_index[lpuart_n]->LPUEN&LPUART_LPUEN_RXEN_MASK))
        lpuart_index[lpuart_n]->LPUEN|=LPUART_LPUEN_RXEN_MASK;
}

dma_channel_enum lpuart_tx_dma[1]={
    DMA2_CHANNEL4,
};

dma_channel_enum lpuart_rx_dma[1]={
    DMA2_CHANNEL6,
};

void lpuart_rx_dma_init(lpuart_index_enum lpuart_n,uint8 priority)
{
    while(!(lpuart_index[lpuart_n]->LPUEN&LPUART_LPUEN_DMAR_MASK))
        lpuart_index[lpuart_n]->LPUEN|=LPUART_LPUEN_DMAR_MASK;
    dma_clock_init(lpuart_rx_dma[lpuart_n]);
    DMA_CH_SET_CPAR(lpuart_rx_dma[lpuart_n],(uint32)(&(lpuart_index[lpuart_n]->LPURXD)));
    DMA_CH(lpuart_rx_dma[lpuart_n]).CCR=0X00000000;
    DMA_CH(lpuart_rx_dma[lpuart_n]).CCR&=~DMA_CCR_DIR_MASK;
    DMA_CH(lpuart_rx_dma[lpuart_n]).CCR|=DMA_CCR_CIRC_MASK;
    DMA_CH(lpuart_rx_dma[lpuart_n]).CCR&=~DMA_CCR_PINC_MASK;
    DMA_CH(lpuart_rx_dma[lpuart_n]).CCR|=DMA_CCR_MINC_MASK;
    DMA_CH(lpuart_rx_dma[lpuart_n]).CCR|=DMA_CCR_MSIZE(0);
    DMA_CH(lpuart_rx_dma[lpuart_n]).CCR|=DMA_CCR_PSIZE(0);
    DMA_CH(lpuart_rx_dma[lpuart_n]).CCR|=DMA_CCR_PL(3);
    DMA_CH(lpuart_rx_dma[lpuart_n]).CCR&=~DMA_CCR_MEM2MEM_MASK;
    
    dma_finish_nvic_enable(lpuart_rx_dma[lpuart_n],priority);
}

void lpuart_rx_dma_start(lpuart_index_enum lpuart_n,uint8*buf,uint32 len)
{
    DMA_CH(lpuart_rx_dma[lpuart_n]).CCR&=~(DMA_CCR_EN_MASK);
    DMA_CH(lpuart_rx_dma[lpuart_n]).CMAR=(uint32)buf;
    DMA_CH(lpuart_rx_dma[lpuart_n]).CNDTR=len;
    DMA_CH(lpuart_rx_dma[lpuart_n]).CCR|=DMA_CCR_EN_MASK;
}

void lpuart_rx_dma_stop(lpuart_index_enum lpuart_n)
{
    DMA_CH(lpuart_rx_dma[lpuart_n]).CCR&=~(DMA_CCR_EN_MASK);
    //lpuart_index[lpuart_n]->GCR&=~UART_GCR_DMAMODE_MASK;
}

void lpuart_tx_dma_init(lpuart_index_enum lpuart_n,uint8 priority)
{
    while(!(lpuart_index[lpuart_n]->LPUEN&LPUART_LPUEN_DMAT_MASK))
        lpuart_index[lpuart_n]->LPUEN|=LPUART_LPUEN_DMAT_MASK;
    dma_clock_init(lpuart_tx_dma[lpuart_n]);
    DMA_CH_SET_CPAR(lpuart_tx_dma[lpuart_n],(uint32)(&(lpuart_index[lpuart_n]->LPUTXD)));
    DMA_CH(lpuart_tx_dma[lpuart_n]).CCR=0X00000000;
    DMA_CH(lpuart_tx_dma[lpuart_n]).CCR|=DMA_CCR_DIR_MASK;
    DMA_CH(lpuart_tx_dma[lpuart_n]).CCR&=~DMA_CCR_CIRC_MASK;
    DMA_CH(lpuart_tx_dma[lpuart_n]).CCR&=~DMA_CCR_PINC_MASK;
    DMA_CH(lpuart_tx_dma[lpuart_n]).CCR|=DMA_CCR_MINC_MASK;
    DMA_CH(lpuart_tx_dma[lpuart_n]).CCR|=DMA_CCR_MSIZE(0);
    DMA_CH(lpuart_tx_dma[lpuart_n]).CCR|=DMA_CCR_PSIZE(0);
    DMA_CH(lpuart_tx_dma[lpuart_n]).CCR|=DMA_CCR_PL(2);
    DMA_CH(lpuart_tx_dma[lpuart_n]).CCR&=~DMA_CCR_MEM2MEM_MASK;
    dma_finish_nvic_enable(lpuart_tx_dma[lpuart_n],priority);
}

void lpuart_tx_dma_start(lpuart_index_enum lpuart_n,const uint8*buf,uint32 len)
{
    DMA_CH(lpuart_tx_dma[lpuart_n]).CCR&=~(DMA_CCR_EN_MASK);
    DMA_CH(lpuart_tx_dma[lpuart_n]).CMAR=(uint32)buf;
    DMA_CH(lpuart_tx_dma[lpuart_n]).CNDTR=len;
    DMA_CH(lpuart_tx_dma[lpuart_n]).CCR|=DMA_CCR_EN_MASK;
}

void lpuart_tx_dma_stop(lpuart_index_enum lpuart_n)
{
    DMA_CH(lpuart_tx_dma[lpuart_n]).CCR&=~(DMA_CCR_EN_MASK);
}
